# -*- coding: utf-8 -*-
"""
文件选择对话框组件
集成系统文件选择对话框，实现路径验证和默认路径设置
"""

import os
import pygame
from typing import Optional, Callable
from pathlib import Path
from gui.components.base_component import BaseComponent
from gui.styles.colors import get_theme_color
from gui.styles.fonts import get_font

# Windows系统文件对话框
try:
    import tkinter as tk
    from tkinter import filedialog, messagebox
    HAS_TKINTER = True
except ImportError:
    HAS_TKINTER = False


class FileDialog(BaseComponent):
    """文件选择对话框组件
    
    提供文件和文件夹选择功能，集成系统原生对话框
    """
    
    def __init__(self, x: int, y: int, width: int, height: int, 
                 dialog_type: str = 'folder'):
        super().__init__(x, y, width, height)
        
        # 对话框类型：'folder', 'file_open', 'file_save'
        self.dialog_type = dialog_type
        
        # 当前选择的路径
        self.selected_path = ''
        self.default_path = os.path.expanduser('~/Downloads')  # 默认下载目录
        
        # 文件过滤器（用于文件选择）
        self.file_filters = [
            ('所有文件', '*.*'),
            ('视频文件', '*.mp4;*.avi;*.mkv;*.flv;*.mov'),
            ('音频文件', '*.mp3;*.wav;*.flac;*.aac')
        ]
        
        # 回调函数
        self.on_path_selected: Optional[Callable[[str], None]] = None
        self.on_path_changed: Optional[Callable[[str], None]] = None
        
        # 样式配置
        self.font = get_font('body_small')
        self.background_color = get_theme_color('input_bg')
        self.border_color = get_theme_color('border')
        self.text_color = get_theme_color('text')
        self.placeholder_color = get_theme_color('text_secondary')
        
        # 按钮样式
        self.button_color = get_theme_color('button')
        self.button_hover_color = get_theme_color('button_hover')
        self.button_text_color = get_theme_color('button_text')
        
        # 组件状态
        self.button_hovered = False
        
        # 初始化按钮矩形
        self._update_button_rect()
        
        # 初始化默认路径
        self._ensure_default_path()
    
    def _ensure_default_path(self):
        """确保默认路径存在"""
        try:
            Path(self.default_path).mkdir(parents=True, exist_ok=True)
        except Exception as e:
            print(f"创建默认路径失败: {e}")
            self.default_path = os.path.expanduser('~')
    
    def set_default_path(self, path: str):
        """设置默认路径
        
        Args:
            path: 默认路径
        """
        if os.path.exists(path):
            self.default_path = path
        else:
            print(f"警告：默认路径不存在: {path}")
    
    def set_file_filters(self, filters: list):
        """设置文件过滤器
        
        Args:
            filters: 文件过滤器列表，格式：[('描述', '*.ext1;*.ext2'), ...]
        """
        self.file_filters = filters
    
    def validate_path(self, path: str) -> bool:
        """验证路径有效性
        
        Args:
            path: 要验证的路径
            
        Returns:
            bool: 路径是否有效
        """
        if not path:
            return False
        
        try:
            path_obj = Path(path)
            
            if self.dialog_type == 'folder':
                # 文件夹必须存在或可创建
                return path_obj.exists() or self._can_create_directory(path)
            else:
                # 文件路径的父目录必须存在
                return path_obj.parent.exists()
        except Exception:
            return False
    
    def _can_create_directory(self, path: str) -> bool:
        """检查是否可以创建目录"""
        try:
            path_obj = Path(path)
            # 检查父目录是否存在且可写
            parent = path_obj.parent
            return parent.exists() and os.access(parent, os.W_OK)
        except Exception:
            return False
    
    def open_dialog(self) -> Optional[str]:
        """打开系统文件选择对话框
        
        Returns:
            Optional[str]: 选择的路径，如果取消则返回None
        """
        if not HAS_TKINTER:
            print("错误：未安装tkinter，无法使用文件对话框")
            return None
        
        selected_path = None
        root = None
        
        try:
            # 创建隐藏的根窗口
            root = tk.Tk()
            root.withdraw()  # 隐藏主窗口
            root.attributes('-topmost', True)  # 置顶显示
            
            if self.dialog_type == 'folder':
                # 文件夹选择对话框
                selected_path = filedialog.askdirectory(
                    title='选择下载文件夹',
                    initialdir=self.default_path
                )
            
            elif self.dialog_type == 'file_open':
                # 文件打开对话框
                filetypes = [(desc, pattern) for desc, pattern in self.file_filters]
                selected_path = filedialog.askopenfilename(
                    title='选择文件',
                    initialdir=self.default_path,
                    filetypes=filetypes
                )
            
            elif self.dialog_type == 'file_save':
                # 文件保存对话框
                filetypes = [(desc, pattern) for desc, pattern in self.file_filters]
                selected_path = filedialog.asksaveasfilename(
                    title='保存文件',
                    initialdir=self.default_path,
                    filetypes=filetypes
                )
            
        except Exception as e:
            print(f"打开文件对话框失败: {e}")
            selected_path = None
        
        finally:
            # 确保根窗口被销毁
            if root:
                try:
                    root.destroy()
                except Exception:
                    pass
        
        if selected_path:
            # 验证选择的路径
            if self.validate_path(selected_path):
                self.selected_path = selected_path
                
                # 触发回调
                if self.on_path_selected:
                    try:
                        self.on_path_selected(selected_path)
                    except Exception as e:
                        print(f"路径选择回调失败: {e}")
                if self.on_path_changed:
                    try:
                        self.on_path_changed(selected_path)
                    except Exception as e:
                        print(f"路径变更回调失败: {e}")
                
                return selected_path
            else:
                print(f"选择的路径无效: {selected_path}")
        
        return None
    
    def _show_error(self, message: str):
        """显示错误消息"""
        if HAS_TKINTER:
            try:
                root = tk.Tk()
                root.withdraw()
                messagebox.showerror('错误', message)
                root.destroy()
            except Exception:
                print(f"错误: {message}")
        else:
            print(f"错误: {message}")
    
    def handle_event(self, event: pygame.event.Event) -> bool:
        """处理事件"""
        if not self.visible or not self.enabled:
            return False
        
        if event.type == pygame.MOUSEMOTION:
            # 检查鼠标是否悬停在按钮上
            old_hovered = self.button_hovered
            self.button_hovered = self.button_rect.collidepoint(event.pos)
            
            if old_hovered != self.button_hovered:
                return True
        
        elif event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1 and self.button_rect.collidepoint(event.pos):
                # 点击浏览按钮
                self.open_dialog()
                return True
        
        return False
    
    def _update_button_rect(self):
        """更新按钮矩形位置"""
        button_width = 80
        button_height = self.height - 4
        self.button_rect = pygame.Rect(
            self.x + self.width - button_width - 2,
            self.y + 2,
            button_width,
            button_height
        )
    
    def update(self, dt: float):
        """更新组件状态"""
        # 更新按钮矩形位置
        self._update_button_rect()
    
    def draw(self, surface: pygame.Surface):
        """绘制组件"""
        if not self.visible:
            return
        
        # 绘制背景
        pygame.draw.rect(surface, self.background_color, self.rect)
        pygame.draw.rect(surface, self.border_color, self.rect, 1)
        
        # 绘制路径文本
        self._draw_path_text(surface)
        
        # 绘制浏览按钮
        self._draw_browse_button(surface)
    
    def _draw_path_text(self, surface: pygame.Surface):
        """绘制路径文本"""
        text_rect = pygame.Rect(
            self.x + 8,
            self.y + 2,
            self.width - 90,  # 留出按钮空间
            self.height - 4
        )
        
        # 创建文本区域的裁剪矩形
        surface.set_clip(text_rect)
        
        if self.selected_path:
            # 显示选择的路径
            display_text = self.selected_path
            
            # 如果路径太长，显示省略号
            text_width = self.font.get_size(display_text)[0]
            if text_width > text_rect.width:
                # 从右侧截取路径
                while text_width > text_rect.width - 20 and len(display_text) > 10:
                    display_text = '...' + display_text[4:]
                    text_width = self.font.get_size(display_text)[0]
            
            text_surface = self.font.render(display_text, True, self.text_color)
        else:
            # 显示占位符文本
            placeholder_text = {
                'folder': '点击浏览选择文件夹...',
                'file_open': '点击浏览选择文件...',
                'file_save': '点击浏览保存文件...'
            }.get(self.dialog_type, '点击浏览...')
            
            text_surface = self.font.render(placeholder_text, True, self.placeholder_color)
        
        # 垂直居中显示文本
        text_y = self.y + (self.height - text_surface.get_height()) // 2
        surface.blit(text_surface, (text_rect.x, text_y))
        
        # 取消裁剪
        surface.set_clip(None)
    
    def _draw_browse_button(self, surface: pygame.Surface):
        """绘制浏览按钮"""
        # 按钮颜色
        button_color = self.button_hover_color if self.button_hovered else self.button_color
        
        # 绘制按钮背景
        pygame.draw.rect(surface, button_color, self.button_rect)
        pygame.draw.rect(surface, self.border_color, self.button_rect, 1)
        
        # 绘制按钮文本
        button_text = '浏览...'
        text_surface = self.font.render(button_text, True, self.button_text_color)
        
        # 居中显示文本
        text_x = self.button_rect.x + (self.button_rect.width - text_surface.get_width()) // 2
        text_y = self.button_rect.y + (self.button_rect.height - text_surface.get_height()) // 2
        surface.blit(text_surface, (text_x, text_y))
    
    def get_selected_path(self) -> str:
        """获取选择的路径"""
        return self.selected_path
    
    def set_selected_path(self, path: str):
        """设置选择的路径
        
        Args:
            path: 要设置的路径
        """
        if self.validate_path(path):
            self.selected_path = path
            if self.on_path_changed:
                self.on_path_changed(path)
        else:
            print(f"警告：设置的路径无效: {path}")
    
    def clear_selection(self):
        """清空选择"""
        self.selected_path = ''
        if self.on_path_changed:
            self.on_path_changed('')
    
    @property
    def position(self):
        """获取组件位置"""
        return super().position
    
    @position.setter
    def position(self, pos):
        """设置组件位置并更新按钮矩形"""
        super(FileDialog, self.__class__).position.fset(self, pos)
        self._update_button_rect()
    
    @property
    def size(self):
        """获取组件大小"""
        return super().size
    
    @size.setter
    def size(self, size):
        """设置组件大小并更新按钮矩形"""
        super(FileDialog, self.__class__).size.fset(self, size)
        self._update_button_rect()


class FolderDialog(FileDialog):
    """文件夹选择对话框"""
    
    def __init__(self, x: int, y: int, width: int, height: int):
        super().__init__(x, y, width, height, 'folder')


class FileOpenDialog(FileDialog):
    """文件打开对话框"""
    
    def __init__(self, x: int, y: int, width: int, height: int):
        super().__init__(x, y, width, height, 'file_open')


class FileSaveDialog(FileDialog):
    """文件保存对话框"""
    
    def __init__(self, x: int, y: int, width: int, height: int):
        super().__init__(x, y, width, height, 'file_save')